"""
Anthropic (Claude) API适配器
支持原生Anthropic API和兼容的中继服务
"""

import logging
from typing import Optional, Dict, Any, AsyncIterator, List, Union
import anthropic
from anthropic import AsyncAnthropic
import asyncio
from .base import ModelConfig, BaseModelAdapter, ModelResponse

logger = logging.getLogger(__name__)

class AnthropicAdapter(BaseModelAdapter):
    """Anthropic API适配器"""
    
    def __init__(self, config: Union[Dict[str, Any], ModelConfig]):
        """
        初始化Anthropic适配器
        
        Args:
            config: 配置字典或ModelConfig对象
        """
        # 转换字典格式为ModelConfig对象
        if isinstance(config, dict):
            config = ModelConfig(
                api_key=config.get('apiKey') or config.get('api_key'),
                api_base=config.get('apiBase') or config.get('api_base') or config.get('baseUrl'),
                model_name=config.get('modelName') or config.get('model_name', 'claude-3-opus-20240229'),
                temperature=config.get('temperature', 0.7),
                max_tokens=config.get('maxTokens') or config.get('max_tokens', 2000),
                provider='anthropic'
            )
        
        # 设置实例变量（在父类初始化之前）
        self.api_key = config.api_key
        self.api_base = config.api_base
        self.model_name = config.model_name
        
        # 调用父类初始化
        super().__init__(config)
        
    def _initialize_client(self) -> None:
        """初始化Anthropic客户端"""
        try:
            # 处理API基础URL
            base_url = self.api_base
            if base_url:
                # 移除末尾的斜杠
                base_url = base_url.rstrip('/')
                # 如果URL以/v1结尾，移除它（SDK会自动添加）
                if base_url.endswith('/v1'):
                    base_url = base_url[:-3]
                # 如果是标准Anthropic API，base_url应该是None
                if 'api.anthropic.com' in base_url:
                    base_url = None

            logger.info(f"初始化Anthropic客户端 - Base URL: {base_url}, Model: {self.model_name}")

            # 设置Claude Code客户端标识头
            default_headers = {
                "anthropic-client": "claude-code",
                "user-agent": "claude-code/1.0"
            }

            # 创建同步客户端
            if base_url:
                self.client = anthropic.Anthropic(
                    api_key=self.api_key,
                    base_url=base_url,
                    default_headers=default_headers
                )
            else:
                self.client = anthropic.Anthropic(
                    api_key=self.api_key,
                    default_headers=default_headers
                )

            # 创建异步客户端
            if base_url:
                self.async_client = AsyncAnthropic(
                    api_key=self.api_key,
                    base_url=base_url,
                    default_headers=default_headers
                )
            else:
                self.async_client = AsyncAnthropic(
                    api_key=self.api_key,
                    default_headers=default_headers
                )

            logger.info("Anthropic客户端初始化成功")

        except Exception as e:
            logger.error(f"初始化Anthropic客户端失败: {e}")
            raise
    
    async def generate(self, messages: List[Dict[str, str]], **kwargs) -> ModelResponse:
        """
        异步生成文本
        
        Args:
            messages: 消息列表
            **kwargs: 其他参数
            
        Returns:
            ModelResponse对象
        """
        try:
            # 获取参数
            max_tokens = kwargs.get('max_tokens', self.config.max_tokens)
            temperature = kwargs.get('temperature', self.config.temperature)
            
            logger.info(f"调用Anthropic API - Model: {self.model_name}, Max Tokens: {max_tokens}")
            
            # 调用异步API
            response = await self.async_client.messages.create(
                model=self.model_name,
                messages=messages,
                max_tokens=max_tokens,
                temperature=temperature
            )
            
            # 提取文本
            content = response.content[0].text if response.content else ""
            logger.info(f"Anthropic API响应成功 - 输出长度: {len(content)}")
            
            # 返回ModelResponse对象
            return ModelResponse(
                content=content,
                model=self.model_name,
                usage={
                    "prompt_tokens": response.usage.input_tokens if response.usage else 0,
                    "completion_tokens": response.usage.output_tokens if response.usage else 0,
                    "total_tokens": (response.usage.input_tokens + response.usage.output_tokens) if response.usage else 0
                },
                finish_reason="stop"
            )
            
        except Exception as e:
            logger.error(f"Anthropic生成失败: {e}")
            raise
    
    async def stream(self, messages: List[Dict[str, str]], **kwargs) -> AsyncIterator[str]:
        """
        流式生成文本
        
        Args:
            messages: 消息列表
            **kwargs: 其他参数
            
        Yields:
            生成的文本片段
        """
        try:
            # 获取参数
            max_tokens = kwargs.get('max_tokens', self.config.max_tokens)
            temperature = kwargs.get('temperature', self.config.temperature)
            
            logger.info(f"流式调用Anthropic API - Model: {self.model_name}")
            
            # 创建流式响应
            stream = await self.async_client.messages.create(
                model=self.model_name,
                messages=messages,
                max_tokens=max_tokens,
                temperature=temperature,
                stream=True
            )
            
            # 处理流式响应
            async for chunk in stream:
                if chunk.type == 'content_block_delta':
                    if hasattr(chunk.delta, 'text'):
                        yield chunk.delta.text
                        
        except Exception as e:
            logger.error(f"Anthropic流式生成失败: {e}")
            raise
    
    def count_tokens(self, text: str) -> int:
        """估算文本的token数量"""
        # 简单估算：1个token约为4个字符（英文）或1个中文字符
        chinese_chars = sum(1 for char in text if '\u4e00' <= char <= '\u9fff')
        other_chars = len(text) - chinese_chars
        return chinese_chars + (other_chars // 4)
    
    def estimate_cost(self, prompt_tokens: int, completion_tokens: int) -> float:
        """估算使用成本"""
        # Claude模型价格（每1000个token的USD价格）
        model_prices = {
            'claude-sonnet-4-20250514': {'input': 0.012, 'output': 0.036},
            'claude-3-5-sonnet-20241022': {'input': 0.003, 'output': 0.015},
            'claude-3-5-haiku-20241022': {'input': 0.001, 'output': 0.005},
            'claude-3-opus-20240229': {'input': 0.015, 'output': 0.075}
        }
        
        prices = model_prices.get(self.model_name, {'input': 0.003, 'output': 0.015})
        input_cost = (prompt_tokens / 1000) * prices['input']
        output_cost = (completion_tokens / 1000) * prices['output']
        return input_cost + output_cost
    
    async def health_check(self) -> bool:
        """健康检查"""
        try:
            response = await self.async_client.messages.create(
                model=self.model_name,
                messages=[{'role': 'user', 'content': 'Hi'}],
                max_tokens=5
            )
            return bool(response.content)
        except Exception as e:
            logger.error(f"健康检查失败: {e}")
            return False
    
    def _prepare_messages(self, prompt: str) -> List[Dict[str, str]]:
        """
        准备消息格式
        
        Args:
            prompt: 提示词或对话历史
            
        Returns:
            消息列表
        """
        # 如果prompt已经是消息列表格式
        if isinstance(prompt, list):
            return prompt
            
        # 尝试解析特殊格式的prompt
        messages = []
        
        # 检查是否包含System/Human/Assistant标记
        if 'System:' in prompt or 'Human:' in prompt:
            lines = prompt.split('\n\n')
            system_prompt = None
            
            for line in lines:
                if line.startswith('System:'):
                    system_prompt = line[7:].strip()
                elif line.startswith('Human:'):
                    if system_prompt:
                        # Anthropic的系统提示词通过第一个用户消息传递
                        messages.append({
                            'role': 'user',
                            'content': f"{system_prompt}\n\n{line[6:].strip()}"
                        })
                        system_prompt = None
                    else:
                        messages.append({
                            'role': 'user',
                            'content': line[6:].strip()
                        })
                elif line.startswith('Assistant:') and line != 'Assistant:':
                    messages.append({
                        'role': 'assistant',
                        'content': line[10:].strip()
                    })
        
        # 如果没有解析出消息，将整个prompt作为用户消息
        if not messages:
            messages = [{'role': 'user', 'content': prompt}]
            
        # 确保最后一条消息是用户消息
        if messages and messages[-1]['role'] == 'assistant':
            messages.append({'role': 'user', 'content': 'Continue.'})
            
        return messages
    
